﻿using System;
using System.IO;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace LightingReflectionApp
{
    public partial class MainForm : Form
    {
        private DataGridView lampDataGrid, reflectiveObjectsDataGrid;
        private TextBox lengthTextBox, widthTextBox, heightTextBox, heightSurfaceTextBox;
        private MenuStrip menuStrip;
        private ToolStripMenuItem fileMenuItem, modelMenuItem, diagramsMenuItem;

        public MainForm()
        {
            InitializeComponent();
            AddComponent();
        }

        private void AddComponent()
        {
            this.Text = "Освещенность помещения";
            this.Size = new Size(770, 660);
            this.MaximizeBox = false;

            menuStrip = new MenuStrip();

            // File menu
            fileMenuItem = new ToolStripMenuItem("Файл");
            var saveMenuItem = new ToolStripMenuItem("Сохранить", null, SaveMenuItem_Click);
            var loadMenuItem = new ToolStripMenuItem("Загрузить", null, LoadMenuItem_Click);
            var clearAllMenuItem = new ToolStripMenuItem("Очистить всё", null, ClearAllMenuItem_Click);
            var quitMenuItem = new ToolStripMenuItem("Выйти", null, QuitMenuItem_Click);
            fileMenuItem.DropDownItems.AddRange(new ToolStripMenuItem[] { saveMenuItem, loadMenuItem, clearAllMenuItem, quitMenuItem });

            // Model menu
            modelMenuItem = new ToolStripMenuItem("Моделирование");
            var startMenuItem = new ToolStripMenuItem("Начать моделирование", null, StartMenuItem_Click);
            modelMenuItem.DropDownItems.Add(startMenuItem);

            // Diagrams menu
            diagramsMenuItem = new ToolStripMenuItem("Диаграммы");
            var ilumLampsMenuItem = new ToolStripMenuItem("Освещение от ламп", null, IlumLampsMenuItem_Click);
            var ilumPrimaryReflectionMenuItem = new ToolStripMenuItem("Первичное отражение", null, IlumPrimaryReflectionMenuItem_Click);
            var ilumSecondaryReflectionMenuItem = new ToolStripMenuItem("Вторичное отражение", null, IlumSecondaryReflectionMenuItem_Click);
            var ilumSumMenuItem = new ToolStripMenuItem("Суммарное освещение", null, IlumSumMenuItem_Click);
            diagramsMenuItem.DropDownItems.AddRange(new ToolStripMenuItem[] { ilumLampsMenuItem, ilumPrimaryReflectionMenuItem, ilumSecondaryReflectionMenuItem, ilumSumMenuItem });

            menuStrip.Items.AddRange(new ToolStripMenuItem[] { fileMenuItem, modelMenuItem, diagramsMenuItem });

            // Controls for room dimensions
            Label roomLabel = new Label { Text = "РАЗМЕРЫ ПОМЕЩЕНИЯ:", Location = new Point(20, 30), Width = 200 };
            Label lengthLabel = new Label { Text = "Длина, L (м):", Location = new Point(40, 60) };
            Label widthLabel = new Label { Text = "Ширина, W (м):", Location = new Point(40, 90) };
            Label heightLabel = new Label { Text = "Высота, H (м):", Location = new Point(40, 120) };
            Label heightSurfaceLabel = new Label { Text = "Высота расчётной поверхности над полом, h (м):", Location = new Point(20, 160), AutoSize = true, MaximumSize = new Size(180, 0) };

            lengthTextBox = new TextBox { Location = new Point(250, 60), Width = 100 };
            widthTextBox = new TextBox { Location = new Point(250, 90), Width = 100 };
            heightTextBox = new TextBox { Location = new Point(250, 120), Width = 100 };
            heightSurfaceTextBox = new TextBox { Location = new Point(250, 160), Width = 100 };

            // DataGridView for lamps
            Label lampsLabel = new Label { Text = "ЛАМПЫ:", Location = new Point(20, 195) };
            lampDataGrid = new DataGridView { Location = new Point(20, 220), Size = new Size(810, 150), ColumnCount = 5, AllowUserToAddRows = true, AllowUserToDeleteRows = true };
            lampDataGrid.Columns[0].Name = "Координата x, (м)";
            lampDataGrid.Columns[1].Name = "Координата y, (м)";
            lampDataGrid.Columns[2].Name = "Координата z, (м)";
            lampDataGrid.Columns[3].Name = "Мощность, P (Вт)";
            lampDataGrid.Columns[4].Name = "Цветовая температура, T (К)";
            lampDataGrid.Columns[4].Width = 170; // Устанавливаем ширину столбца, чтобы надпись поместилась

            // DataGridView for reflective objects
            Label objectsLabel = new Label { Text = "ОБЪЕКТЫ:", Location = new Point(20, 380) };
            reflectiveObjectsDataGrid = new DataGridView { Location = new Point(20, 405), Size = new Size(810, 150), ColumnCount = 6, AllowUserToAddRows = true, AllowUserToDeleteRows = true };
            reflectiveObjectsDataGrid.Columns[0].Name = "Координата x, (м)";
            reflectiveObjectsDataGrid.Columns[1].Name = "Координата y, (м)";
            reflectiveObjectsDataGrid.Columns[2].Name = "Ширина, (м)";
            reflectiveObjectsDataGrid.Columns[3].Name = "Длина, (м)";
            reflectiveObjectsDataGrid.Columns[4].Name = "Высота над полом, (м)";
            reflectiveObjectsDataGrid.Columns[5].Name = "Коэффициент отражения";
            reflectiveObjectsDataGrid.Columns[5].Width = 150; // Устанавливаем ширину столбца, чтоб надпись поместилась

            this.Controls.Add(menuStrip);
            this.MainMenuStrip = menuStrip;
            this.Controls.Add(roomLabel);
            this.Controls.Add(lengthLabel);
            this.Controls.Add(widthLabel);
            this.Controls.Add(heightLabel);
            this.Controls.Add(heightSurfaceLabel);
            this.Controls.Add(lengthTextBox);
            this.Controls.Add(widthTextBox);
            this.Controls.Add(heightTextBox);
            this.Controls.Add(heightSurfaceTextBox);
            this.Controls.Add(lampsLabel);
            this.Controls.Add(lampDataGrid);
            this.Controls.Add(objectsLabel);
            this.Controls.Add(reflectiveObjectsDataGrid);
        }

        private void SaveMenuItem_Click(object sender, EventArgs e)
        {
            SaveFileDialog saveFileDialog = new SaveFileDialog();
            if (saveFileDialog.ShowDialog() == DialogResult.OK)
            {
                // Сохранение данных в файл
                using (StreamWriter writer = new StreamWriter(saveFileDialog.FileName))
                {
                    writer.WriteLine(lengthTextBox.Text);
                    writer.WriteLine(widthTextBox.Text);
                    writer.WriteLine(heightTextBox.Text);
                    writer.WriteLine(heightSurfaceTextBox.Text);

                    foreach (DataGridViewRow row in lampDataGrid.Rows)
                    {
                        if (row.Cells[0].Value != null &&
                        row.Cells[1].Value != null &&
                        row.Cells[2].Value != null &&
                        row.Cells[3].Value != null &&
                        row.Cells[4].Value != null)
                        {
                            writer.WriteLine($"{row.Cells[0].Value};{row.Cells[1].Value};{row.Cells[2].Value};{row.Cells[3].Value};{row.Cells[4].Value}");
                        }
                    }

                    foreach (DataGridViewRow row in reflectiveObjectsDataGrid.Rows)
                    {
                        if (row.Cells[0].Value != null &&
                        row.Cells[1].Value != null &&
                        row.Cells[2].Value != null &&
                        row.Cells[3].Value != null &&
                        row.Cells[4].Value != null &&
                        row.Cells[5].Value != null)
                        {
                            writer.WriteLine($"{row.Cells[0].Value};{row.Cells[1].Value};{row.Cells[2].Value};{row.Cells[3].Value};{row.Cells[4].Value};{row.Cells[5].Value}");
                        }
                    }
                }
            }
        }

        private void LoadMenuItem_Click(object sender, EventArgs e)
        {
            OpenFileDialog openFileDialog = new OpenFileDialog();
            if (openFileDialog.ShowDialog() == DialogResult.OK)
            {
                // Загрузка данных из файла
                using (StreamReader reader = new StreamReader(openFileDialog.FileName))
                {
                    lengthTextBox.Text = reader.ReadLine();
                    widthTextBox.Text = reader.ReadLine();
                    heightTextBox.Text = reader.ReadLine();
                    heightSurfaceTextBox.Text = reader.ReadLine();

                    lampDataGrid.Rows.Clear();
                    reflectiveObjectsDataGrid.Rows.Clear();

                    while (!reader.EndOfStream)
                    {
                        string[] values = reader.ReadLine().Split(';');
                        if (values.Length == 5)
                        {
                            lampDataGrid.Rows.Add(values);
                        }
                        else
                            if (values.Length == 6)
                            {
                            reflectiveObjectsDataGrid.Rows.Add(values);
                            }
                    }
                }
            }
        }

        private void ClearAllMenuItem_Click(object sender, EventArgs e)
        {
            lengthTextBox.Clear();
            widthTextBox.Clear();
            heightTextBox.Clear();
            heightSurfaceTextBox.Clear();
            lampDataGrid.Rows.Clear();
            reflectiveObjectsDataGrid.Rows.Clear();
        }

        private void QuitMenuItem_Click(object sender, EventArgs e)
        {
            Application.Exit();
        }

        private void StartMenuItem_Click(object sender, EventArgs e)
        {
            double length, width, height, surfaceHeight;

            lampDataGrid.EndEdit();                 //закрываем строку для чтения
            reflectiveObjectsDataGrid.EndEdit();    //аналогично

            if (double.TryParse(lengthTextBox.Text, out length) && length > 0 &&
                double.TryParse(widthTextBox.Text, out width) && width > 0 &&
                double.TryParse(heightTextBox.Text, out height) && height > 0 &&
                double.TryParse(heightSurfaceTextBox.Text, out surfaceHeight) &&
                surfaceHeight <= height && surfaceHeight >= 0)
            {
                List<Lamp> lamps = new List<Lamp>();
                bool lampsOK = true;

                foreach (DataGridViewRow row in lampDataGrid.Rows)
                {
                    if (row.Cells[0].Value != null &&
                        row.Cells[1].Value != null &&
                        row.Cells[2].Value != null &&
                        row.Cells[3].Value != null &&
                        row.Cells[4].Value != null)
                    {
                        double x, y, z, power;
                        int colorTemperature;

                        if (double.TryParse(row.Cells[0].Value.ToString(), out x) && x >= 0 &&
                            double.TryParse(row.Cells[1].Value.ToString(), out y) && y >= 0 &&
                            double.TryParse(row.Cells[2].Value.ToString(), out z) && z >= 0 && z <= height &&
                            double.TryParse(row.Cells[3].Value.ToString(), out power) && power > 0 &&
                            Int32.TryParse(row.Cells[4].Value.ToString(), out colorTemperature) && colorTemperature > 0)

                            lamps.Add(new Lamp(x, y, z, power, colorTemperature));
                        else
                        {
                            lampsOK = false;
                            MessageBox.Show("Пожалуйста, введите корректные параметры ламп.");
                            break;
                        }
                    }
                }

                List<ReflectiveObject> reflectiveObjects = new List<ReflectiveObject>();
                bool objectsOK = true;

                foreach (DataGridViewRow row in reflectiveObjectsDataGrid.Rows)
                {
                    if (row.Cells[0].Value != null &&
                        row.Cells[1].Value != null &&
                        row.Cells[2].Value != null &&
                        row.Cells[3].Value != null &&
                        row.Cells[4].Value != null &&
                        row.Cells[5].Value != null)
                    {
                        double x, y, widthObj, lengthObj, heightAboveFloor, reflectionCoefficient;

                        if (double.TryParse(row.Cells[0].Value.ToString(), out x) && x >= 0 &&
                            double.TryParse(row.Cells[1].Value.ToString(), out y) && y >= 0 &&
                            double.TryParse(row.Cells[2].Value.ToString(), out widthObj) && widthObj > 0 &&
                            double.TryParse(row.Cells[3].Value.ToString(), out lengthObj) && lengthObj > 0 &&
                            double.TryParse(row.Cells[4].Value.ToString(), out heightAboveFloor) && heightAboveFloor >= 0 &&
                            double.TryParse(row.Cells[5].Value.ToString(), out reflectionCoefficient) && reflectionCoefficient >= 0 && reflectionCoefficient <= 1)
                        {
                            reflectiveObjects.Add(new ReflectiveObject(new Point((int)x, (int)y), new Size((int)widthObj, (int)lengthObj), heightAboveFloor, reflectionCoefficient));
                        }
                        else
                        {
                            objectsOK = false;
                            MessageBox.Show("Пожалуйста, введите корректные параметры объектов.");
                            break;
                        }
                    }
                }

                if (lampsOK && objectsOK)
                {
                    Room room = new Room(length, width, height, 0.1, 0, 0.9); // squareSide = 0.1, floorReflectionCoefficient = 0, ceilingReflectionCoefficient = 0.9
                    foreach (var obj in reflectiveObjects)
                    {
                        room.AddReflectiveObject(obj);
                    }

                    Surface lampSurface = new Surface(surfaceHeight, room);
                    Surface primaryReflectedSurface = new Surface(surfaceHeight, room);
                    Surface secondaryReflectedSurface = new Surface(surfaceHeight, room);
                    ReflectiveSurface reflectiveSurface = new ReflectiveSurface(room);

                    IlluminationCalculator lampCalculator = new IlluminationCalculator(room, lamps, lampSurface);
                    IlluminationCalculator primaryReflectCalculator = new IlluminationCalculator(room, lamps, primaryReflectedSurface, reflectiveSurface);
                    IlluminationCalculator secondaryReflectCalculator = new IlluminationCalculator(room, lamps, secondaryReflectedSurface, reflectiveSurface);

                    lampCalculator.CalculateIlluminationFromLamps();
                    primaryReflectCalculator.CalculateReflectedIllumination();
                    
                    //вторичное отражение
                    secondaryReflectCalculator.CalculateSecondaryReflectedIllumination();
     
                    Surface summedSurface = lampSurface.DeepCopy().Add(primaryReflectedSurface).Add(secondaryReflectedSurface);
                    IlluminationCalculator sumCalculator = new IlluminationCalculator(room, lamps, summedSurface, reflectiveSurface);

                    // Сохраняем калькуляторы в полях формы для последующего использования в меню Diagram
                    lampIlluminationCalculator = lampCalculator;
                    primaryReflectionCalculator = primaryReflectCalculator;
                    secondaryReflectionCalculator = secondaryReflectCalculator;
                    sumIlluminationCalculator = sumCalculator;

                    MessageBox.Show("Моделирование завершено.");
                }
            }
            else
            {
                MessageBox.Show("Пожалуйста, введите корректные значения для помещения и освещенной поверхности. Десятичный знак - запятая.");
            }
        }

        private void IlumLampsMenuItem_Click(object sender, EventArgs e)
        {
            if (lampIlluminationCalculator != null)
            {
                IlluminationForm illuminationForm = new IlluminationForm(lampIlluminationCalculator, "Свет от ламп");
                illuminationForm.ShowDialog();
            }
            else
            {
                MessageBox.Show("Необходимо сначала провести моделирование.");
            }
        }

        private void IlumPrimaryReflectionMenuItem_Click(object sender, EventArgs e)
        {
            if (primaryReflectionCalculator != null)
            {
                IlluminationForm illuminationForm = new IlluminationForm(primaryReflectionCalculator, "Первичное отражение");
                illuminationForm.ShowDialog();
            }
            else
            {
                MessageBox.Show("Необходимо сначала провести моделирование.");
            }
        }

        private void IlumSecondaryReflectionMenuItem_Click(object sender, EventArgs e)
        {
            if (secondaryReflectionCalculator != null)
            {
                IlluminationForm illuminationForm = new IlluminationForm(secondaryReflectionCalculator, "Вторичное отражение");
                illuminationForm.ShowDialog();
            }
            else
            {
                MessageBox.Show("Необходимо сначала провести моделирование.");
            }
        }

        private void IlumSumMenuItem_Click(object sender, EventArgs e)
        {
            if (sumIlluminationCalculator != null)
            {
                IlluminationForm illuminationForm = new IlluminationForm(sumIlluminationCalculator, "Суммарная освещенность");
                illuminationForm.ShowDialog();
            }
            else
            {
                MessageBox.Show("Необходимо сначала провести моделирование.");
            }
        }

        private IlluminationCalculator lampIlluminationCalculator;
        private IlluminationCalculator primaryReflectionCalculator;
        private IlluminationCalculator secondaryReflectionCalculator;
        private IlluminationCalculator sumIlluminationCalculator;
    }
}
